package com.fh.controller.call;

import com.fh.callService.UncallAPIBindingStub;
import com.fh.callService.UncallAPILocator;
import com.fh.controller.base.BaseController;
import com.fh.model.loan.*;
import com.fh.service.cuijimanage.CuijimanageServiceImpl;
import com.fh.service.cuijimanage.HisOverdueBillInfoService;
import com.fh.util.Const;
import com.fh.util.PhoneUtil;
import com.fh.util.UserUtils;
import com.fh.util.UuidUtil;
import com.uns.inf.acms.client.DynamicConfigLoader;
import com.ybd.common.component.redis.StringRedisUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.xml.rpc.ServiceException;
import java.rmi.RemoteException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 电话呼叫
 * 创建者：shanlin
 * 创建时间：2017/8/19 15:30
 **/
@Controller
@RequestMapping("/call")
public class CallController extends BaseController {

    private static Logger loger = LoggerFactory.getLogger(CallController.class);

    @Autowired
    private CuijimanageServiceImpl cuijimanageServiceImpl;
    
    @Autowired
    private HisOverdueBillInfoService hisOverdueBillInfoService;

    @Autowired
    private StringRedisUtil stringRedisUtil;

    /**
     * 获取被呼叫人信息
     * @param uContactsInfoId 联系人id
     * @param callLoanNid 催收编号
     * @param borrowNid
     * @param anjianUserId 案件用户
     * @return
     * @throws Exception
     */
    @RequestMapping("/getCalled")
    @ResponseBody
    public Object getCalled(String uContactsInfoId,String callLoanNid,String borrowNid,String anjianUserId) throws Exception {
        Map<String,Object> contactsInfoMap = new HashMap<>(16);
		//点击的是借款人的朋友 进行电话催收
        if(borrowNid == null){
            Map<String,Object> parameter = new HashMap<>(16);
            parameter.put("id", uContactsInfoId);
            parameter.put("callLoanNid",callLoanNid);
            contactsInfoMap = cuijimanageServiceImpl.findContactsInfoById(parameter);
        }else{//点击的是借款人 进行电话催收
            Map<String, Object> map = new HashMap<>(16);
            map.put("userId", anjianUserId);
            map.put("callLoanNid", StringUtils.trimAllWhitespace(callLoanNid));
            CallLoanInfo callLoanInfo = cuijimanageServiceImpl.findCallLoanInfoByUserId(map);
            //获取借款人详情    接口改ETL
            CallLoanUserInfo resultMap = null;
            if(callLoanInfo != null) {
                if ("2".equals(callLoanInfo.getProductSource())) {
                    //获取现金贷
                    resultMap = cuijimanageServiceImpl.getUserInfoByType(anjianUserId, "1");
                } else if ("6".equals(callLoanInfo.getProductSource())) {
                    //获取卡贷
                    resultMap = cuijimanageServiceImpl.getUserInfoByType(anjianUserId, "2");
                } else {
                    //今日现金一期老数据
                    logger.info("CallController  callLoanInfo.getProductSource()  ---> [非现金贷,卡贷来源。未知来源]");
                    resultMap = cuijimanageServiceImpl.getUserInfoByType(anjianUserId, "1");
                }
            } else {
                logger.info("CallController cuijimanageServiceImpl.findCallLoanInfoByUserId  获取案件信息为null");
            }
            //联系人
            contactsInfoMap.put("contUserName",callLoanInfo.getRealName());
            //催收员
            contactsInfoMap.put("callUser",callLoanInfo.getCallUser());
            //催收对象
            contactsInfoMap.put("realName",callLoanInfo.getRealName());
            contactsInfoMap.put("callLoanNid",callLoanNid);
            //借款人联系方式
            contactsInfoMap.put("mobile",(resultMap !=null ?
                    (Objects.equals("topC",borrowNid) ? resultMap.getComTel() : resultMap.getMobile()) : ""));
            //联系人类型 4为借款人  5 通讯录
            contactsInfoMap.put("contType", Objects.equals("book",borrowNid) ? "5" :"4");
        }
        logger.info("获取参数平台 callServiceIp = {}" + getCallServiceIp());
        //映射外网ip
        contactsInfoMap.put("callServiceIp",getCallServiceIp());

        return contactsInfoMap.size() > 0 ? contactsInfoMap : new HashMap<>();
    }


    /**
     * 保存通话记录
     * @param callLoanConverseInfo
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/saveCall",method= RequestMethod.POST)
    @ResponseBody
    public Object saveCall(CallLoanConverseInfo callLoanConverseInfo) throws Exception {
        String file = callLoanConverseInfo.getCallInfo();
        boolean hasFiles = (null != file || !"".equals(file));
        String callInfo = hasFiles ? file : "无录音";
        callLoanConverseInfo.setCallInfo(callInfo);
        callLoanConverseInfo.setCallType(2);
        callLoanConverseInfo.setStatus(0);
        callLoanConverseInfo.setConverseTime("");
        callLoanConverseInfo.setCreateTime(new Date());
        callLoanConverseInfo.setUpdateTime(new Date());
        return cuijimanageServiceImpl.insertCallLoanConverseInfo(callLoanConverseInfo);
    }
    
    
    /**
     * 保存详情页 催收记录
     * @param callLoanLog
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/saveCallLoanLog",method= RequestMethod.POST)
    @ResponseBody
    public Object saveCallLoanLog(CallLoanLog callLoanLog) throws Exception {
        return cuijimanageServiceImpl.addRecord(callLoanLog);
    }

    /**
     * 拨号
     * @param toTel  被叫号码
     * @throws ServiceException
     * @throws RemoteException
     */
    @RequestMapping("/onClickCall")
    @ResponseBody
    public Object onClickCall(String toTel){
    	Map<String, String> nodeMap = null;
    	try {
    		nodeMap = getNodeMap(getCall().onClickCall(getExten(),toTel, UuidUtil.get32UUID()));
    		loger.info("点击呼叫信息-->"+ nodeMap);
		} catch (Exception e) {
			loger.error("呼叫异常信息", e);
		}
    	return nodeMap;
    }

    /**
     * 挂断
     * @throws ServiceException
     * @throws RemoteException
     */
    @RequestMapping("/hangUp")
    @ResponseBody
    public Object hangUp() throws ServiceException, RemoteException{
        return getNodeMap(getCall().hangUp(getExten()));
    }

    /**
     * 弹屏
     * @return
     * @throws ServiceException
     * @throws RemoteException
     */
    @RequestMapping("/popEvent")
    @ResponseBody
    public Object popEvent() throws ServiceException, RemoteException{
		loger.info("弹屏ing");
        return getNodeMap(getCall().popEvent(getExten()));
    }

    /**
     * 获取录音文件名
     * @throws ServiceException
     * @throws RemoteException
     */
    @RequestMapping("/getRecording")
    @ResponseBody
    private Object getRecording(String uid) throws ServiceException, RemoteException {
        return getNodeMap(getCall().getRecording(uid));
    }

    /**
     * 获取分机状态
     * @return  status:状态、其中（0 空闲、8 振铃、4 不在线 、1 通话中	11 示忙）
     * @throws ServiceException
     * @throws RemoteException
     */
    @RequestMapping("/getExtenStatus")
    @ResponseBody
    public Object getExtenStatus() throws ServiceException, RemoteException {
		loger.info("获取分机状态");
        return getNodeMap(getCall().getExtenStatus(getExten()));
    }

    /**
     * 获取分机号
     * @return
     */
    @RequestMapping("/getMachineNum")
    @ResponseBody
    public Object getMachineNum(){
		loger.info("获取分机号");
        String machineNum = getExten();
        return machineNum != null ? machineNum : "";
    }

    /**
     * 将xml解析成map类型
     * @param xml （String）
     * @return
     */
    private static Map<String,String> getNodeMap(String xml) {
        Map<String, String> map = new HashMap<>(16);
        try {
			//将xml转为dom对象
            Document doc =  DocumentHelper.parseText(xml);
			//获取根节点
            Element root = doc.getRootElement();
            readEle(root,map);
        }catch (Exception e) {
			loger.error("将xml解析成map类型异常-->", e);
        }
        return map;
    }

    /**
     * 递归xml
     * @param e
     * @param map
     */
    private static void readEle(Element e,Map<String, String> map){
        //判断是否有复合内容
        if(e.hasMixedContent()){
            Iterator it = e.elementIterator();
            while (it.hasNext()) {
                e = (Element) it.next();
                //递归
                readEle(e,map);
            }
        }else{
			//获取所有没有子节点的节点  =》 key和value
            map.put(e.getName(), e.getTextTrim());
        }
    }

    private static UncallAPIBindingStub getCall() throws ServiceException {
        UncallAPILocator service = new UncallAPILocator();
        service.setUncallAPIPortAddress(getCallServiceIp());
        return (UncallAPIBindingStub) service.getUncallAPIPort();
    }

    private static String getCallServiceIp(){//参数平台获取数据
        return Const.Call_SERVICE_IP;
    }

    /**
     * 获取当前登陆人分机号
     * @return
     */
    private String getExten(){
        return UserUtils.getUser().getMachineNum();
    }

    /**
     * 从参数平台更新配置
     */
    @RequestMapping("/update")
    @ResponseBody
    public String updateParam(){
        return Const.Call_SERVICE_IP = DynamicConfigLoader.getByEnv("callServiceIp");
    }
    
    
    @RequestMapping("getCallShip")
    @ResponseBody
    public Object getCallShip(){
        return Const.CALLSHIPMAP;
    }
    
    @RequestMapping("getCallResult")
    @ResponseBody
    public Object getCallResult(){
        return Const.CALLRESULTMAPN;
    }
    
    /**
     * 获取手机号归属地
     * @param mobile
     * @return
     */
    @RequestMapping("/{tableIndex}/getMobileAddr/{mobile}")
    @ResponseBody
    public String getMobileAddr(@PathVariable("tableIndex") String index,@PathVariable("mobile") String mobile){
        String province = null;
        String key = "province" + mobile;
        Object o = stringRedisUtil.get(key);
        if(o != null){
            loger.info("==================getMobileAddr==========  "+o.toString());
            return o.toString();
        }

        Map<String, String> map = PhoneUtil.getPhoneInfo(mobile);
        if (map != null){
            province = map.get("province");
            stringRedisUtil.put(key,province,30, TimeUnit.DAYS);
        }
        return  province;
    }
}
